use lazy_static::lazy_static;
use std::sync::{LazyLock, Mutex};

/*
静态常量
全局常量可以在程序任何一部分使用，当然，如果它是定义在某个模块中，你需要引入对应的模块才能使用。常量，顾名思义它是不可变的，很适合用作静态配置：



常量与普通变量的区别
关键字是const而不是let
定义常量必须指明类型（如 i32）不能省略
定义常量时变量的命名规则一般是全部大写
常量可以在任意作用域进行定义，其生命周期贯穿整个程序的生命周期。编译时编译器会尽可能将其内联到代码中，所以在不同地方对同一常量的引用并不能保证引用到相同的内存地址
常量的赋值只能是常量表达式/数学表达式，也就是说必须是在编译期就能计算出的值，如果需要在运行时才能得出结果的值比如函数，则不能赋值给常量表达式
对于变量出现重复的定义(绑定)会发生变量遮盖，后面定义的变量会遮住前面定义的变量，常量则不允许出现重复的定义


lazy_static
lazy_static是社区提供的非常强大的宏，用于懒初始化静态变量，之前的静态变量都是在编译期初始化的，因此无法使用函数调用进行赋值，而lazy_static允许我们在运行期初始化静态变量！
使用lazy_static在每次访问静态变量时，会有轻微的性能损失，因为其内部实现用了一个底层的并发原语std::sync::Once，在每次访问该变量时，程序都会执行一次原子指令用于确认静态变量的初始化是否完成。
*/

lazy_static! {
    static ref NAMES: Mutex<String> = Mutex::new(String::from("Sunface, Jack, Allen"));
}
pub fn run1() {
    let mut v = NAMES.lock().unwrap();
    v.push_str(", Myth");
    println!("{}", v);
}

use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP:  std::collections::HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
}

pub fn run2() {
    // 首次访问`HASHMAP`的同时对其进行初始化
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());

    // 后续的访问仅仅获取值，再不会进行任何初始化操作
    println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap());
}


/*
Box::leak
Box::leak可以用于全局变量，例如用作运行期初始化的全局动态配置
它可以将一个变量从内存中泄漏(听上去怪怪的，竟然做主动内存泄漏)，然后将其变为'static生命周期，最终该变量将和程序活得一样久，因此可以赋值给全局静态变量CONFIG。




*/

/* 

#[derive(Debug)]
struct Config {
    a: String,
    b: String
}

static mut CONFIG: Option<&mut Config> = None;



fn init() -> Option<&'static mut Config> {
    let c = Box::new(Config {
        a: "A".to_string(),
        b: "B".to_string(),
    });

    Some(Box::leak(c))
}

pub  fn run3(){
     unsafe {
        CONFIG = init();

        println!("{:?}", CONFIG)
    }
}

*/


/*
标准库中的 Once 和 Lazy 
Lazy 会自动按需加载内容，让代码更简洁，更人性化，而 Once 则可以手动指定初始化的时机或使用不同的方法初始化，更强大


*/

use std::{sync::OnceLock, thread};

#[derive(Debug)]
struct Logger;

// 使用 OnceLock 来创建全局的、线程安全的单例
// OnceLock 保证 Logger 只被初始化一次，即使多个线程同时调用 get_or_init
static LOGGER: OnceLock<Logger> = OnceLock::new();

impl Logger {
    // 获取全局 Logger 实例的静态引用
    // 返回 &'static Logger 表示引用在整个程序生命周期内有效
    fn global() -> &'static Logger {
        // get_or_init 是线程安全的：
        // - 如果 Logger 还未初始化，执行闭包进行初始化
        // - 如果已经初始化，直接返回已有的引用
        // - 多个线程同时调用时，只有一个线程会执行初始化，其他线程会等待
        LOGGER.get_or_init(|| {
            println!("Logger is being created..."); // 初始化打印 - 这行只会执行一次
            Logger  // 创建并返回 Logger 实例
        })
    }

    // Logger 的日志方法
    fn log(&self, message: String) {
        println!("{}", message)
    }
}

pub fn run4() {
    // 创建新线程
    let handle = thread::spawn(|| {
        // 在新线程中获取全局 Logger 实例
        // 这可能是第一次初始化，也可能是获取已存在的实例
        let logger = Logger::global();
        logger.log("thread message".to_string()); // 线程中的日志
    });

    // 在主线程中获取全局 Logger 实例
    // 如果子线程先执行，这里会获取已初始化的实例
    // 如果主线程先执行，这里会进行初始化
    let logger = Logger::global();
    logger.log("some message".to_string()); // 主线程的第一条日志

    // 再次获取全局 Logger 实例（不会重新初始化）
    let logger2 = Logger::global();
    logger2.log("other message".to_string()); // 主线程的第二条日志

    // 等待子线程结束
    handle.join().unwrap();
    
    // 运行结果说明：
    // "Logger is being created..." 只会打印一次，证明单例模式工作正常
    // 无论哪个线程先执行，OnceLock 都保证线程安全
}




#[derive(Debug)]
struct  lazyLog;

static lazylock: LazyLock<lazyLog> = LazyLock::new(lazyLog::new);

impl lazyLog {
    fn new() ->lazyLog{
         println!("Logger is being created...");
        lazyLog
    }

     fn log(&self, message: String) {
        println!("{}", message)
    }
}

pub  fn run5(){

    let hand=thread::spawn(move ||{
        let log = &lazylock;
        log.log("thread message".to_string());
    });

    let log =&lazylock;
    log.log("some message".to_string());

    let log=&lazylock;
    log.log("other message".to_string());

    hand.join().unwrap();
}


pub fn run() {
    run5();
    //run4();
    //run1();
    //run2();
    //run3();
}
